package com.cc.app.ui;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.PointFEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

import com.cc.app.util.Utils;
import com.cc.app.game.GameStateListener;
import com.cc.app.module.ImagePiece;

import java.util.Collections;
import java.util.List;
import com.cc.app.R;

/**
 *
 */
public class MainView extends View implements View.OnTouchListener {

    private List<ImagePiece> parts;

    private Context context;

    private GameInfo game = GameInfo.ONE;

    private Paint paint;

    private int clicked = 0;

    private int gap = 2;

    private int selectRow = -1;

    private int selectCol = -1;

    private int blankRow = -1;

    private int blankCol = -1;

    private PointF p1;
    private PointF p2;

    private boolean isMoving = false;

    private GameStateListener mSuccessListener;

    private boolean success = false;

    public MainView(Context context, AttributeSet attr) {
        super(context, attr);
        this.context = context;
        this.paint = new Paint(Paint.ANTI_ALIAS_FLAG);

        setBackImg(R.mipmap.sdhy);
        setOnTouchListener(this);
    }

    public void setBackImg(int img) {
        if (game.getImage() == img)
            return;

        game.changeImage(img);
        reset();
    }

    public void changeMode(String gameMode) {
        if (game.getMode().equals(gameMode))
            return;

        game.changeMode(gameMode);
        reset();
    }

    public void reset() {
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), game.getImage());
        parts = Utils.splitImage(context, bitmap, game.getCount(), game.getMode());
        success = false;
        gap = 2;
        clicked = 0;

        Collections.shuffle(parts);

        if (game.isNormalMode()) {
            if (parts.get(parts.size() - 1).getType() != ImagePiece.TYPE_EMPTY) {
                for (int i = 0; i < parts.size(); i++) {
                    if (parts.get(i).getType() == ImagePiece.TYPE_EMPTY) {
                        ImagePiece tmp = parts.get(i);
                        parts.set(i, parts.get(parts.size() - 1));
                        parts.set(parts.size() - 1, tmp);
                        break;
                    }
                }
            }

            blankRow = blankCol = game.getCount() - 1;
            p1 = getPoint(blankRow, blankCol);
        } else {
            blankRow = -1;
            blankCol = -1;
            p1 = null;
        }

        invalidate();
    }

    public void setGameListener(GameStateListener listener) {
        this.mSuccessListener = listener;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (isMoving || success)
            return true;

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            action(event);
        }

        return true;
    }

    private void action(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();
        int count = game.getCount();

        int width = getWidth() / count;
        int hegith = getHeight() / count;

        if (blankRow == -1) {
            blankCol = x / width;
            blankRow = y / hegith;
        } else {
            selectCol = x / width;
            selectRow = y / hegith;
        }

        if (game.isNormalMode() && Math.pow(blankRow - selectRow, 2) + Math.pow(blankCol - selectCol, 2) == 1) {
            p1 = getPoint(blankRow, blankCol);
            p2 = getPoint(selectRow, selectCol);
            move();

            clicked++;
            invalidate();
        } else if (!game.isNormalMode()) {
            if (blankRow >= 0 && selectRow >= 0) {
                p1 = getPoint(blankRow, blankCol);
                p2 = getPoint(selectRow, selectCol);

                move();
            }

            invalidate();
        }
    }

    private void move() {
        ValueAnimator firstAnimator = ValueAnimator.ofObject(new PointFEvaluator(p1), p1, p2);
        ValueAnimator secondAnimator = ValueAnimator.ofObject(new PointFEvaluator(p2), p2, p1);

        AnimatorSet as = new AnimatorSet();
        as.play(firstAnimator).with(secondAnimator);
        as.setDuration(200);

        ValueAnimator.AnimatorUpdateListener listener = new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                invalidate();
            }
        };

        firstAnimator.addUpdateListener(listener);

        as.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                isMoving = false;

                int index1 = blankRow * game.getCount() + blankCol;
                int index2 = selectRow * game.getCount() + selectCol;

                ImagePiece tmp = parts.get(index1);
                parts.set(index1, parts.get(index2));
                parts.set(index2, tmp);

                if (game.isNormalMode()) {
                    blankRow = selectRow;
                    blankCol = selectCol;
                    selectRow = selectCol = -1;
                    p1 = getPoint(blankRow, blankCol);
                    p2 = null;
                } else {
                    blankRow = blankCol = -1;
                    selectRow = selectCol = -1;
                }

                if (checkSuccess()) {
                    invalidate();
                    Toast.makeText(getContext(), "成功!", Toast.LENGTH_SHORT).show();
                    if (mSuccessListener != null) {
                        mSuccessListener.gameSuccess(game.getLevel());
                    }
                }
            }

            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                isMoving = true;
            }
        });
        as.start();
    }

    private PointF getPoint(int row, int col) {
        int count = game.getCount();

        int width = getWidth() / count;
        int hegith = getHeight() / count;

        return new PointF(col * width, row * hegith);
    }

    private boolean checkSuccess() {
        for (int i = 0; i < parts.size(); i++) {
            if (parts.get(i).getIndex() != i)
                return false;
        }

        success = true;
        gap = 0;
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (parts == null || parts.isEmpty())
            return;

        int count = game.getCount();

        int width = getWidth() / count;
        int hegith = getHeight() / count;

        for (int row = 0; row < count; row++) {
            for (int col = 0; col < count; col++) {
                int index = row * count + col;
                ImagePiece ip = parts.get(index);

                RectF rect = new RectF(col * width + gap, row * hegith + gap, (col + 1) * width - gap * 2, (row + 1) * hegith - gap * 2);
                if (isMoving) {
                    if (row == selectRow && col == selectCol && p2 != null) {
                        rect = new RectF(p2.x + gap, p2.y + gap, p2.x + width - gap * 2, p2.y + hegith - gap * 2);
                    } else if (row == blankRow && col == blankCol && p1 != null) {
                        rect = new RectF(p1.x + gap, p1.y + gap, p1.x + width - gap * 2, p1.y + hegith - gap * 2);
                    }

                    canvas.drawBitmap(ip.getBitmap(), null, rect, paint);
                    continue;
                }

                canvas.drawBitmap(ip.getBitmap(), null, rect, paint);

                if (game.getMode() == GameInfo.GAME_MODE_NORMAL) {
                    if (ip.getType() == ImagePiece.TYPE_EMPTY) {
                        paint.setColor(Color.RED);
                        paint.setTextSize(100);

                        paint.setTextAlign(Paint.Align.CENTER);
                        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
                        float top = fontMetrics.top;//为基线到字体上边框的距离,即上图中的top
                        float bottom = fontMetrics.bottom;//为基线到字体下边框的距离,即上图中的bottom

                        int baseLineY = (int) (rect.centerY() - top / 2 - bottom / 2);//基线中间点的y轴计算公式
                        canvas.drawText(String.valueOf(clicked), rect.centerX(), baseLineY, paint);
                    }
                } else if (blankRow == row && blankCol == col || row == selectRow && col == selectCol) {
                    canvas.drawBitmap(ip.getBitmap(), null, rect, paint);
                    Paint colorPaint = new Paint();
                    colorPaint.setARGB(80, 255, 0, 0);
                    canvas.drawRect(rect, colorPaint);
                }
            }
        }
    }

    public int getLevel() {
        return game.getLevel();
    }


}
